#version 450 compatibility



layout(local_size_x = DEF_LocalSize, local_size_y = DEF_LocalSize, local_size_z = 1) in;

layout( binding = 0, rgba8ui) uniform uimage2D Pix;

layout( binding = 0 ) uniform Buf_LoalParameter0 {
    ivec4   m_Box;
    ivec2   m_Offset;
    uint    m_PointNum;
    uint    m_IntersectPointNum;
    uint    m_Func;
    float   m_LineWidth;
    float   m_VartualLineGap;
};

layout( binding = 1 ) uniform Buf_LoalParameter1 {
    uint m_Color;
};
layout(std430, binding = 2) buffer Buf_GlobalParameter2 {
    vec2 m_Lines[];
};


shared uint LineLen;
shared uint global_localID;
shared float HStep;
shared float VStep;
shared int LineWidthOffset;

shared vec2 lineDir;
shared vec2 tmpPosA;
shared vec2 tmpPosB;
shared uvec4 c;
shared bool Break = false;


void main(){
    const uint id = (gl_WorkGroupID.y * gl_NumWorkGroups.x) + gl_WorkGroupID.x;
    //const uint id = (gl_WorkGroupID.y * gl_NumWorkGroups.x) + gl_WorkGroupID.x;
    uint localID = gl_LocalInvocationIndex;

    

    uint endID = id+1;
    if(m_Func != 0){
        if(endID >= m_PointNum) return;
    }
    
    if(localID == 0){
        
        //切换绘制线方式
        //----------------线位置起点和终点-----------------
        switch(m_Func){
        case 0:
        case 1: //连续线
            if(endID >= m_PointNum) endID = 0;
            tmpPosA = m_Lines[id + 1 ];
            tmpPosB = m_Lines[endID + 1];
            break;
        case 2:
            endID = (id+1)*2;
            tmpPosA = m_Lines[ endID ];
            tmpPosB = m_Lines[ endID + 1];
            break;
        }
        
        lineDir = (tmpPosB - tmpPosA);
        
        //LineLen = uint(abs(distance(tmpPosB, tmpPosA)));
        if(m_LineWidth>1){
            LineWidthOffset = int(round((m_LineWidth+0.5)/2.0));
        } else {
            LineWidthOffset = 1;
        }
        
        if(abs(lineDir.x) > abs(lineDir.y)){
            HStep =   (abs(lineDir.x) / abs(lineDir.y)) ;
            LineLen = uint(abs(distance(tmpPosB.x, tmpPosA.x)));
        }else{
            VStep =   (abs(lineDir.y) / abs(lineDir.x)) ;
            LineLen = uint(abs(distance(tmpPosB.y, tmpPosA.y)));
        }

        
        lineDir = normalize(lineDir);
        
        global_localID = 0;

        c = uvec4(bitfieldExtract(m_Color, 0, 8), 
                    bitfieldExtract(m_Color, 8, 8), 
                    bitfieldExtract(m_Color, 16, 8), 
                    bitfieldExtract(m_Color, 24, 8));
    }
    barrier();

    //if(Break) return;
    
    ivec2 coord = ivec2(0);
    ivec2 OffsetCorrd = coord;
    for(int i=0; ; ){
        i = int(global_localID + localID);
        
        bool continueLoop = true;
        if(m_VartualLineGap > 0){
            int vartualGapID = int(i / m_VartualLineGap);
            if( (vartualGapID&0x1) == 0) continueLoop = false;
        }


        uvec4 AAC = c;
        if(i < LineLen && continueLoop){
            int X = i * int(sign(lineDir.x));
            int Y = i * int(sign(lineDir.y));

            
            //vec2 tc = lineDir * i;
            if(abs(lineDir.x) > abs(lineDir.y)) {
                coord.x = X;
                coord.y = Y/int(HStep+0.6);
            } else {
                int Step = (X)/int(VStep*0.5);
                coord.x = X/int(VStep);
                coord.y = Y;
            }
            
            coord.x += int(tmpPosA.x);
            coord.y += int(tmpPosA.y);
            
            //coord.x += m_Offset.x;
            //coord.y += m_Offset.y;
            
            if(coord.x < m_Box.x || coord.y < m_Box.y || coord.x >= m_Box.z || coord.y >= m_Box.w){


                
            }else{
                //coord += m_Box.xy;

                imageStore(Pix, coord, c);
            
                if(m_LineWidth > 1.0){
                    if(abs(lineDir.x) >= abs(lineDir.y)) {
                        OffsetCorrd = coord;
                        for(float i=0; i<LineWidthOffset; i+=1){
                            imageStore(Pix, OffsetCorrd, c);
                            OffsetCorrd.y += 1;
                        }
                        OffsetCorrd = coord;
                        for(float i=0; i<=LineWidthOffset+1; i+=1){
                            imageStore(Pix, OffsetCorrd, c);
                            OffsetCorrd.y -= 1;
                        }
                    } else {
                        OffsetCorrd = coord;
                        for(float i=0; i<LineWidthOffset; i+=1){
                            imageStore(Pix, OffsetCorrd, c);
                            OffsetCorrd.x += 1;
                        }
                        OffsetCorrd = coord;
                        for(float i=0; i<=LineWidthOffset+1; i+=1){
                            imageStore(Pix, OffsetCorrd, c);
                            OffsetCorrd.x -= 1;
                        }
                    }
                }
                
                
                
                uvec4 color;
                OffsetCorrd = coord;
                if(abs(lineDir.x) >= abs(lineDir.y)) {
                    
                    OffsetCorrd.y += LineWidthOffset;
                    color = imageLoad(Pix, OffsetCorrd);
                    AAC.r = uint(float(color.r)*(1-lineDir.y) + float(c.r)*lineDir.y);
                    AAC.g = uint(float(color.g)*(1-lineDir.y) + float(c.g)*lineDir.y);
                    AAC.b = uint(float(color.b)*(1-lineDir.y) + float(c.b)*lineDir.y);

                    imageStore(Pix, OffsetCorrd, AAC);

                    OffsetCorrd.y -= LineWidthOffset+1;
                    color = imageLoad(Pix, OffsetCorrd);
                    AAC.r = uint(float(color.r)*(1-lineDir.y) + float(c.r)*lineDir.y);
                    AAC.g = uint(float(color.g)*(1-lineDir.y) + float(c.g)*lineDir.y);
                    AAC.b = uint(float(color.b)*(1-lineDir.y) + float(c.b)*lineDir.y);
                    
                    imageStore(Pix, OffsetCorrd, AAC);

                } else {
                    OffsetCorrd.x += LineWidthOffset;
                    color = imageLoad(Pix, OffsetCorrd);
                    AAC.r = uint(float(color.r)*(1-lineDir.x) + float(c.r)*lineDir.x);
                    AAC.g = uint(float(color.g)*(1-lineDir.x) + float(c.g)*lineDir.x);
                    AAC.b = uint(float(color.b)*(1-lineDir.x) + float(c.b)*lineDir.x);
                    
                    imageStore(Pix, OffsetCorrd, AAC);

                    OffsetCorrd.x -= LineWidthOffset+1;
                    color = imageLoad(Pix, OffsetCorrd);
                    AAC.r = uint(float(color.r)*(1-lineDir.x) + float(c.r)*lineDir.x);
                    AAC.g = uint(float(color.g)*(1-lineDir.x) + float(c.g)*lineDir.x);
                    AAC.b = uint(float(color.b)*(1-lineDir.x) + float(c.b)*lineDir.x);

                    imageStore(Pix, OffsetCorrd, AAC);

                }
            }

            
        }
        barrier();

        if(global_localID >= LineLen) break;
        if(localID == 0){
            global_localID += DEF_LocalSize*DEF_LocalSize;
        }
        barrier();
        

        
    }

}





